package com.wangbo.validate;

import com.wangbo.test.util.ResultObjUtil;
import com.wangbo.test.util.model.CustomException;
import com.wangbo.test.util.model.ResultObj;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.validation.ConstraintViolationException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.stream.Collectors;

@RestControllerAdvice
public class GlobalControllerAdvice {

    @InitBinder
    public void initBinder(WebDataBinder webDataBinder) {
        webDataBinder.registerCustomEditor(String.class,new StringTrimmerEditor(true));
        webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"), true));
    }

    /**
     * @ExceptionHandler采取就近原则，会从类型最接近的Exception子类开始匹配
     * 500
     */
    @ExceptionHandler(value = Exception.class)
    public ResultObj handleError(Exception e) {
        e.printStackTrace();
        return ResultObjUtil.error(500, "未知异常");
    }

    /**
     * Custom异常处理
     */
    @ExceptionHandler(value = CustomException.class)
    public ResultObj handleError(CustomException e) {
        e.printStackTrace();
        System.out.printf("【参数异常】: %s", e.getMessage());
        return ResultObjUtil.error(e.getCode(), e.getMessage());
    }

    /**
     * validation
     */
    @ExceptionHandler(value = MethodArgumentNotValidException.class)
    public ResultObj handleError(MethodArgumentNotValidException e) {
        e.printStackTrace();
        BindingResult bindingResult = e.getBindingResult();
        String message = bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","));
        System.out.printf("【参数异常】: %s%n", message);
        return ResultObjUtil.error(400, String.format("参数输入有误：【%s】", message));
    }

    /**
     * validation
     */
    @ExceptionHandler(value = BindException.class)
    public ResultObj handleError(BindException e) {
        e.printStackTrace();
        BindingResult bindingResult = e.getBindingResult();
        String message = bindingResult.getAllErrors().stream().map(DefaultMessageSourceResolvable::getDefaultMessage).collect(Collectors.joining(","));
        System.out.printf("【参数异常】: %s%n", message);
        return ResultObjUtil.error(400, String.format("参数输入有误：【%s】", message));
    }

    /**
     * validation
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResultObj handleError(MissingServletRequestParameterException e) {
        e.printStackTrace();
        String message = e.getMessage();
        System.out.printf("【参数异常】: %s%n", message);
        return ResultObjUtil.error(400, String.format("参数输入有误：【%s】", message));
    }

    /**
     * validation
     */
    @ExceptionHandler({ConstraintViolationException.class})
    public ResultObj handleConstraintViolationException(ConstraintViolationException e) {
        e.printStackTrace();
        String message = e.getMessage();
        System.out.printf("【参数异常】: %s%n", message);
        return ResultObjUtil.error(400, String.format("参数输入有误：【%s】", message));
    }
}
